package csel.model;

public class Map implements java.io.Serializable, Observer
{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	Tile[][] tileMatrix;
	private Tile[][] lastCalculatedViewableTiles;
	private Tile lastCenterTile;
	private int lastDx;
	private int lastDy;

	public Map(int width, int height)
	{
		tileMatrix = new Tile[width][height];
	}

	public Map(Tile[][] tile)
	{
		tileMatrix = tile;
	}

	// return tiles
	public Tile getTile(int x, int y)
	{
		try
		{
			return tileMatrix[x][y];
		} catch (ArrayIndexOutOfBoundsException e)
		{
			return null;
		}
	}

	public Tile[][] getAdjacentTiles(Tile tile, int dx, int dy)
	{
		if((tile == lastCenterTile)&&(lastCalculatedViewableTiles != null)&&
				(dx == lastCalculatedViewableTiles.length) &&(dx > 0)&&
				(dy==lastCalculatedViewableTiles[0].length))
		{
			return(lastCalculatedViewableTiles);
		}
		else
		{
			return(calculateViewableTiles(tile,dx,dy));
		}
		
	}

	public Tile[][] getTileMatrix()
	{
		return tileMatrix;
	}

	public void setTileMatrix(Tile[][] tileMatrix)
	{
		this.tileMatrix = tileMatrix;
	}

	public void modelUpdate(Object subject)
	{
		if(subject instanceof Entity)
		{
			Tile nt = ((Entity)subject).getLocation();
			if(!nt.equals(lastCenterTile))
			{
				calculateViewableTiles(nt, lastDx, lastDy);
			}
		}
	}
	private Tile[][] calculateViewableTiles(Tile tile, int dx, int dy)
	{
		lastDx = dx;
		lastDy = dy;
		lastCenterTile = tile;
		int dxLength = 2 * Math.abs(dx);
		int dyLength = 2 * Math.abs(dy);
		Location locTemp = tile.getLocation();
		if (locTemp == null)
		{
			return null;
		}

		int xTile = locTemp.getX();
		int yTile = locTemp.getY();
		RealTile[][] newTile = new RealTile[dxLength + 1][dyLength + 1];

		// logic for getting the coordinates translated. if below dx or dy then
		// it
		// is subtracted a right amount, if above dx or dy then it is added the
		// right amount
		for (int i = 0; i <= dxLength; i++)
		{
			for (int j = 0; j <= dyLength; j++)
			{
				int xTemp = xTile - (dx - i);
				int yTemp = yTile - (dy - j);
				try
				{
					newTile[i][j] = (RealTile) tileMatrix[xTemp][yTemp];
				} catch (ArrayIndexOutOfBoundsException e)
				{
				}
			}
		}
		lastCalculatedViewableTiles = newTile;
		return newTile;
	}
}
